import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;


/**
 * 
 * This class is for the basic military unit
 *
 */
public class Unit {
	
	/*
	 * Separated mutators and accessors are recommended.
	 * Here provides the example for HP;
	 * more properties, like damage, can be added following this way.
	 */
	public static final int UNIT_TYPE_ID_TANK = 1;
	public static final int UNIT_TYPE_ID_MOBILEAA = 2;
	public static final int UNIT_TYPE_ID_INFANTRY = 3;
	public static final int UNIT_TYPE_ID_BATTLESHIP = 4;
	public static final int UNIT_TYPE_ID_JET = 5;
	
	public static final int UNIT_SIDE_ID_COMPUTER = 0;
	public static final int UNIT_SIDE_ID_USER1 = 1;
	public static final int UNIT_SIDE_ID_USER2 = 2;
	
	protected int unitTypeID;
	protected String unitName;
	protected String unitDescription;
	protected int hitPoint;
	protected int remainingHitPoint;
	protected int attackPower;
	protected int defensePower;
	protected int motionPoint;
	protected Point unitCoord;	// Unit's coordinate inside the map
	
	protected int unitImageIndex;
	protected ArrayList<BufferedImage> unitImagesList;
	
	protected boolean isSelected;	// True if the unit is selected (by AI, user1 or user2.
									// Note that there is only one or less unit could be selected in a time)
	protected boolean isActive;		// True if the unit is still active in a specific turn
	protected int side;		// Indicate the unit is controlled by AI, user1 or user2
	
	protected ArrayList<Point> rltAttackableArea;
	
	/*
	 * Constructors
	 */
	public Unit(Point coord, Integer s) {
		unitCoord = coord;
		unitImagesList = new ArrayList<BufferedImage>();
		side = s;
		isSelected = false;
		isActive = true;
		rltAttackableArea = new ArrayList<Point>();
	}
	
	public Unit() {
		// Do nothing
	}
	
	public Unit(Unit unit) {
		this.unitTypeID = unit.getUnitTypeID();
		this.unitName = new String(unit.getUnitName());
		this.unitDescription = new String(unit.getUnitDescription());
		this.hitPoint = unit.getHitPoint();
		this.remainingHitPoint = unit.getRemainingHitPoint();
		this.attackPower = unit.getAttackPower();
		this.defensePower = unit.getDefensePower();
		this.motionPoint = unit.getMotionPoint();
		this.unitCoord = new Point(unit.getUnitCoord());
		this.unitImageIndex = unit.getUnitImageIndex();
		this.unitImagesList = new ArrayList<BufferedImage>(unit.getUnitImagesList());
		this.isSelected = unit.isSelected();
		this.isActive = unit.isActive();
		this.side = unit.getSide();
		
		this.rltAttackableArea = new ArrayList<Point>();
		for(int i = 0; i < unit.getRltAttackableArea().size(); i++)
			this.rltAttackableArea.add(new Point(unit.getRltAttackableArea().get(i)));
	}
	
	/*
	 * Load unit image
	 */
	protected void addUnitImage(BufferedImage image) {
		unitImagesList.add(image);
	}
	
	/*
	 * Mutators
	 */
	protected void setUnitImageIndex(int index) {
		unitImageIndex = index;
	}
	
	/*
	 * Accessors
	 */
	public BufferedImage getUnitImage() {
		return unitImagesList.get(unitImageIndex);
	}
	
	public int getUnitTypeID() {
		return unitTypeID;
	}
	
	public Point getUnitCoord() {
		return unitCoord;
	}
	
	public int getHitPoint() {
		return hitPoint;
	}
	
	public int getRemainingHitPoint() {
		return remainingHitPoint;
	}
	
	public int getAttackPower(){
		return attackPower;
	}
	
	public int getDefensePower(){
		return defensePower;
	}
	
	public int getMotionPoint(){
		return motionPoint;
	}
	
	public String getUnitName() {
		return unitName;
	}
	
	public String getUnitDescription() {
		return unitDescription;
	}
	
	public int getSide() {
		return side;
	}
	
	public int getUnitImageIndex() {
		return unitImageIndex;
	}
	
	public ArrayList<BufferedImage> getUnitImagesList() {
		return unitImagesList;
	}
	
	public boolean isActive() {
		return isActive;
	}
	
	public boolean isSelected() {
		return isSelected;
	}
	
	public boolean isDestroyed() {
		if(remainingHitPoint <= 0)
			return true;
		return false;
	}
	
	public ArrayList<Point> getRltAttackableArea() {
		return rltAttackableArea;
	}
	
	public ArrayList<Point> getAttackableArea() {
		ArrayList<Point> absAttackableArea = new ArrayList<Point>();
		int index = 0;
		while(index < rltAttackableArea.size()) {
			absAttackableArea.add(new Point(rltAttackableArea.get(index).x + unitCoord.x, rltAttackableArea.get(index).y + unitCoord.y));
			index++;
		}
		return absAttackableArea;
	}
	
	/*
	 * Mutators
	 */
	public void setIsActive(boolean iA) {
		isActive = iA;
	}
	
	public void setIsSelected(boolean iS) {
		isSelected = iS;
	}
	
	public void setUnitCoord(Point uC) {
		unitCoord = uC;
	}
	public void setRemainHP(Integer newHP){
		remainingHitPoint = newHP;
	}
}
